package com.xstudio.pvzreborn.block.entity;

import com.xstudio.pvzreborn.capability.CapManager;
import com.xstudio.pvzreborn.capability.Sunshine;
import com.xstudio.pvzreborn.handle.PVZItemStackHandler;
import com.xstudio.pvzreborn.utils.LevelUtils;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.FloatTag;
import net.minecraft.nbt.IntTag;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.IItemHandler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.List;
import java.util.Objects;
import java.util.function.BiConsumer;

public abstract class PVZMachineBlockEntityBase extends BlockEntity {

	public static final int MAX_ENERGY = 10000;
	private static final PrimitiveTypePair incrementBuf = new PrimitiveTypePair(-1, 0f);
	protected final Sunshine energy = new Sunshine(MAX_ENERGY);
	protected final LazyOptional<Sunshine> energyCapability = LazyOptional.of(() -> energy);
	protected final BiConsumer<PVZItemStackHandler, Integer> onSlotChange = (handler, slot) -> setChanged();

	protected int processTime;
	protected boolean isWorking;

	public PVZMachineBlockEntityBase(BlockEntityType<?> pType, BlockPos pWorldPosition, BlockState pBlockState) {
		super(pType, pWorldPosition, pBlockState);
	}

	public abstract List<IItemHandler> getAllItemStackHandler();

	public int getProcessTime() {
		return processTime;
	}

	public void setProcessTime(int processTime) {
		this.processTime = processTime;
	}

	public boolean isWorking() {
		return isWorking;
	}

	public void tick() {
		if (LevelUtils.canBlockSeeSun(level, getBlockPos())) {
			energy.add(getSunshineEnergyIncrement());
		}
	}

	/**
	 * @author Bread_NiceCat
	 * 用于减少运算次数
	 * 1s 为 20tick
	 * 24000tick为1天
	 * DAY
	 * 0t->6:1s->25sun
	 * 6000t->12://此时应该最多 1s->75sun
	 * 12000t->18: equ 0t
	 * DAY END
	 * f(d)=((-50f/36f)(d-6)^2+75)/20
	 */
	protected float getSunshineEnergyIncrement() {
		int relTime = (int) (level.dayTime() % 24000);
		if (incrementBuf.getFirst() == relTime) {
			return incrementBuf.getSecond();
		}
		float increment = (float) (((-50d / 36d) * Math.pow(relTime / 1000d - 6, 2) + 75) / 20d);
		incrementBuf.setData(relTime, increment);
		return increment;
	}

	@Override
	public void setRemoved() {
		super.setRemoved();
		energyCapability.invalidate();
	}

	@Override
	protected void saveAdditional(CompoundTag pTag) {
		super.saveAdditional(pTag);
		pTag.putBoolean("isWorking", isWorking);
		pTag.put("sunshine_energy", energy.serializeNBT());
		pTag.put("processTime", IntTag.valueOf(processTime));
	}

	@Override
	public void load(@NotNull CompoundTag pTag) {
		super.load(pTag);
		this.isWorking = pTag.getBoolean("isWorking");
		this.processTime = pTag.getInt("processTime");
		this.energy.deserializeNBT((FloatTag) Objects.requireNonNull(pTag.get("sunshine_energy")));
	}

	@NotNull
	@Override
	public <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
		if (cap == CapManager.SUNSHINE) {
			return energyCapability.cast();
		}
		return super.getCapability(cap, side);
	}

	private static final class PrimitiveTypePair {

		int relTime;
		float increment;

		PrimitiveTypePair(int relTime, float increment) {
			this.relTime = relTime;
			this.increment = increment;
		}

		public int getFirst() {
			return relTime;
		}

		public float getSecond() {
			return increment;
		}

		public void setData(int relTime, float increment) {
			this.relTime = relTime;
			this.increment = increment;
		}

	}

}
